package com.org.oracle.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.org.oracle.constant.RedisKeyConstants;
import com.org.oracle.enums.ResponseCodeEnum;
import com.org.oracle.helper.EmailHelper;
import com.org.oracle.exception.CustomException;
import com.org.oracle.service.VerifyCodeService;
import com.org.oracle.sub.dto.EmailCheckDTO;
import com.org.oracle.sub.dto.EmailVerifyCodeDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author: heiye
 * @date: 2024/12/03 下午7:24
 * @version: v1.0.0
 * @description:
 */
@Slf4j
@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Resource
    private EmailHelper emailHelper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource(name = "verifyCodeExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 发送邮件验证码
     *
     * @param emailVerifyCodeDTO
     */
    @Override
    public void sendEmail(EmailVerifyCodeDTO emailVerifyCodeDTO) {
        // 邮箱地址
        String email = emailVerifyCodeDTO.getEmail();

        // 构建验证码 redis key
        String key = RedisKeyConstants.buildEmailVerificationCodeKey(email);

        // 判断是否已发送验证码
//        boolean isSent = redisTemplate.hasKey(key);
//        if (isSent) {
//            throw new CustomException(ResponseCodeEnum.EMAIL_VERIFICATION_CODE_SEND_FREQUENTLY);
//        }

        // 生成 6 位随机数字验证码
        String code = RandomUtil.randomNumbers(6);

        // 验证码过期时间 5 分钟
        Integer timeout = 5;

        log.info("==> 邮箱: {}, 已生成验证码：【{}】", email, code);

        // 异步发送邮箱验证码
        threadPoolTaskExecutor.submit(() -> emailHelper.sendEmail(email, code, String.valueOf(timeout)));

        // 存储验证码到 redis, 并设置过期时间为 5 分钟
        redisTemplate.opsForValue().set(key, code, timeout, TimeUnit.MINUTES);
    }

    /**
     * 邮箱校验
     *
     * @param emailCheckDTO
     */
    @Override
    public void checkEmail(EmailCheckDTO emailCheckDTO) {
        // 获取到邮箱的验证码
        String email = emailCheckDTO.getEmail();
        String verifyCode = (String) redisTemplate.opsForValue().get(RedisKeyConstants.buildEmailVerificationCodeKey(email));

        // 判空并判断验证码是否正确
        if (StringUtils.isEmpty(verifyCode) || !StringUtils.equals(verifyCode, emailCheckDTO.getCode())) {
            throw new CustomException(ResponseCodeEnum.EMAIL_VERIFICATION_CODE_FAIL);
        }
    }
}
